/**
 * Copyright (c) 2009 blurredVision
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#ifndef __JUKEBOX_OPENAL_H__
#define __JUKEBOX_OPENAL_H__

#pragma once
#include "IJukeBox.h"
#include "al/al.h"
#include "StreamingBuffer_OpenAL.h"

#define NR_JB_BUFFERS 4

namespace openAL {

class DLL_EXPORT JukeBox_OpenAL :
	public audio::IJukeBox
{
public:
	JukeBox_OpenAL(ALuint _sourceID);
	virtual ~JukeBox_OpenAL(void);

	/**
	*	Start the JukeBox
	*/
	virtual void play();

	/**
	*	Start the sound by fading in.
	*	\param float fFadeTime
	*/
	virtual void play_fadeIn(float fFadeTime);

	/**
	*	Stop the JukeBox immediatly
	*/
	virtual void stop();

	/**
	*	Fade the music out and stop
	*	\param float fFadeTime;
	*/
	virtual void fadeAndStop(float fFadeTime);

	/**
	*	Skip to next song
	*/
	virtual void nextSong(float _fadeTime);

	/**
	*	Skip to previous song
	*/
	virtual void previousSong(float _fadeTime);
	
	/**
	*	Add a soundfile to the playlist.
	*	Soundfiles are NOT added twice.
	*	
	*	\param std::string
	*	!!! At the moment only ogg-files are supported !!!
	*/
	virtual int addToPlaylist(const std::string &_fileName);
	
	/**
	*	Remove a soundfile from playlist
	*	All used resources are freed
	*	\param std::string 
	*/
	virtual void removeFromPlaylist(const std::string &_fileName);
	
	//void removeFromPlaylist(int index);

	/**
	*	Standard update-method.
	*	Used for doing some shit.
	*	Call once per frame
	*/
	virtual void update(const double &dt);

	/**
	*	Set the overall volume for the JukeBox	
	*/
	virtual void setVolume(float _vol);

	/**
	*	Set the song to start with by playlist number
	*/
	virtual void setCurrentSong(int _number);

	/**
	*	Set the song to start with by filename (without path)
	*/
	virtual void setCurrentSong(const std::string &_filename);

	/**
	*	Return the playlist number of the current song 
	*/
	virtual int getCurrentSong();

	/**
	*	Set intro and loop track for mode JB_INTRO_LOOP
	*	Should always be called before play
	*/
	virtual void setIntroAndLoop(unsigned int _intro, unsigned int _loop);

	/**
	*	\param unsigned int		_blRepeat Number of cycles the base loop
	*							is played inbetween the variations. Default is 1.
	*/
	virtual void setUpLoopVariations(unsigned int _blRepeat);

protected:
	
	struct Song {
		unsigned int ordernr;
		std::string sFilename;
		StreamingBuffer_OpenAL* pBuffer;	
	};

	/*
	*	Fill the buffers and start the source
	*/
	void fillBuffersAndPlay();

	/**
	*	Get the current song
	*/
	Song* getSongByNumber(unsigned int _nr);	

	typedef std::map<std::string, Song*>SongMap; 
	SongMap m_mPlaylist;

	Song* m_CurrentSong;

	unsigned int m_iNumOfSongs; ///< Number of songs in the playlist
	unsigned int m_iCurrentSong; ///< ordernr of current song
	unsigned int m_iLoopTrack;
	unsigned int m_iBaseLoopCycle;
	unsigned int m_iNumberOfBaseLoopRepeats;

	bool m_bShouldBePlaying;	

	float m_fFadeFactor; ///< Stuff for fades
	float m_fDeltaFade; ///< Stuff for fades
	
	// Bufferhandling
	ALuint m_aBuffers[NR_JB_BUFFERS]; ///< Array of ids of open_AL sound-buffer
	unsigned int m_iFreeBuffers;
	unsigned int m_iNextFreeBuffer;	

	ALuint m_sourceID; ///< JukeBox gets its own permanent source


};

}
#endif // __JUKEBOX_OPENAL_H__